﻿#pragma once

#ifndef __STDAFX__
#define __STDAFX__

#define _USE_32BIT_TIME_T
typedef long time_t;
#ifdef __cplusplus
extern "C"{
#endif
#include <ntifs.h>

#include <ntdddisk.h>
#include <ntddstor.h>

#include <ntstrsafe.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
};
#endif
#pragma pack(1)	
typedef unsigned int UINT;
//typedef long time_t;
struct FileRecord;
#ifdef __cplusplus
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS };
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
#define RTL_CONSTANT_STRING(s) { sizeof( s ) - sizeof( (s)[0] ), sizeof( s ), s }
struct TimeStruct{
	time_t StdModTime;
	LARGE_INTEGER KeModTime;
	TIME_FIELDS BrokenModTime;
};


struct DiskListEntry{
	HANDLE CurrentDiskHandle;
	wchar_t DiskIDName[33];
	UNICODE_STRING DiskName;
	PDEVICE_OBJECT device;
	LIST_ENTRY list_item;
	LIST_ENTRY udlist_item;
	struct FBFSVolume *Volume;
};
struct FBFSVolume{
	PDEVICE_OBJECT VolumeDevice;
	LIST_ENTRY FileListHead;
	ULONG primary_size;
	ULARGE_INTEGER extend_size;
	ULONG primary_offest;
	ULARGE_INTEGER extend_offest;
	KMUTEX FileListLock;
	LIST_ENTRY list_item;
	FileRecord *RootDir;
	LIST_ENTRY TreeListHead;
};

class _KeStringW;

struct DirInfo{
	/* 如果第一项是false，那么下面ChildFileTree项是NULL！*/
	bool IsDir;
	/*二叉树式存储结构！*/
	FileRecord *next_sibling_file;/*左手指针，指向同级文件*/
	/* 下面的是指向父目录文件节点的指针，如是根目录就是NULL */
	FileRecord *FatherDir;
	FileRecord *lower_file;/*二叉树的右手指针，指向下级文件*/
};
#ifndef INOUT
#define INOUT
#endif

#define Volume_Sign 0x7f8d403f

struct FileRecord
{
	LIST_ENTRY list_item;
	UNICODE_STRING FileName[2];//第0项是文件名，第1项是完全路径
	FBFSVolume *OnDevice;
	UINT FileLength;
	LARGE_INTEGER offest;
	DirInfo DirStruct;
	TimeStruct ModTime;
	DiskListEntry *OnVolume;
};



union hextonum{
	signed char hexarray[sizeof(long long)];
	unsigned char uhexarray[sizeof(long long)];
	signed char charnum;
	unsigned ucharnum;
	signed short shortnum;
	unsigned short ushortnum;
	signed int intnum;
	unsigned uintnum;
	signed long longnum;
	unsigned long ulongnum;
	signed long long longlongnum;
	unsigned long long ulonglongnum;
};


struct DeviceDesc{
	PDEVICE_OBJECT RealDevice;
	UNICODE_STRING Name;
};

struct FBINST_DSKS 
{
	struct DeviceDesc Devices[20];
	UINT dsknum;
};

struct  Judge_Disk
{
	bool Is;
	PDEVICE_OBJECT LowerDevice;
	UNICODE_STRING IdString;
};




LARGE_INTEGER * StdTimeToKeTime(IN time_t StdTime,OUT LARGE_INTEGER &KeTime);



struct FBFS_DRIVER_EXT 
{
	struct _DRIVER_OBJECT *DriverObject;

	PDEVICE_OBJECT ControlDevice;

	ULONG Count;

	UNICODE_STRING ServicePath;

	UINT DiskNum;
	UINT UDNum;

	LIST_ENTRY DiskListHead,udListHead;

	KMUTEX DiskListLock;
	KMUTEX udListLock;
};

struct UD_Ext 
{
	PDEVICE_OBJECT LowerDevice;
};

struct Lower{
	UNICODE_STRING IdString;
	PDEVICE_OBJECT RealDevice;
};

extern Lower LowerDevices[20];

struct Cache{
	FileRecord *Handle;
	PVOID Buffer;
	LARGE_INTEGER offest;
	ULONG length;
};

extern struct Cache FileCache[10];

extern PDEVICE_OBJECT LowerControl;

extern FBFS_DRIVER_EXT *pDriverExtension;

extern int* except;

extern UNICODE_STRING usDeviceName;
extern UNICODE_STRING usSymlinkName;

extern LIST_ENTRY VolumeHead;

NTSTATUS EasyDeviceControl(PDEVICE_OBJECT CallDevice,ULONG ControlCode,PVOID InBuffer,ULONG InBufSize,PVOID OutBuffer,ULONG OutBufSize);


#define DELAY_ONE_MICROSECOND 	(-10)
#define DELAY_ONE_MILLISECOND	(DELAY_ONE_MICROSECOND*1000)



struct UD_Ext_Flag{
	ULONG Signature; 
	PDRIVER_OBJECT DriverObject;
	struct FBFSVolume *Volume;
	PDEVICE_OBJECT LowerDevice;
};

#pragma pack()

#define DEF_FAT32_SIZE		512 * 2048
#define MIN_FAT16_SIZE		8400 + 1

#define DEF_BASE_SIZE		63
#define MAX_LIST_SIZE		((0x80000 - 0x10000) >> 9)
#define DEF_LIST_SIZE		(MAX_LIST_SIZE * 510)
#define MIN_PRI_SIZE		63 * 256
#define MAX_PRI_SIZE		65535
#define MIN_NAND_ALIGN		255

#define GLOB_BUF_SIZE		64

typedef unsigned char uchar;
typedef UINT16 uchar2;
typedef UINT32 uchar4;

//#ifdef __GNUC__
//#define PACK	__attribute__((packed))
//#else
//#define PACK
//#pragma pack(1)
//#endif
//struct fb_mbr
//{
//	uchar jmp_code;
//	uchar jmp_ofs;
//	uchar boot_code[0x1ab];
//	uchar max_sec;		/* 0x1ad  */
//	uchar2 lba;			/* 0x1ae  */
//	uchar spt;			/* 0x1b0  */
//	uchar heads;			/* 0x1b1  */
//	uchar2 boot_base;		/* 0x1b2  */
//	uchar4 fb_magic;		/* 0x1b4  */
//	uchar mbr_table[0x46];	/* 0x1b8  */
//	uchar2 end_magic;		/* 0x1fe  */
//} PACK;
//
//struct fb_data
//{
//	uchar2 boot_size;		/* 0x200  */
//	uchar2 flags;			/* 0x202  */
//	uchar ver_major;		/* 0x204  */
//	uchar ver_minor;		/* 0x205  */
//	uchar2 list_used;		/* 0x206  */
//	uchar2 list_size;		/* 0x208  */
//	uchar2 pri_size;		/* 0x20a  */
//	uchar4 ext_size;		/* 0x20c  */
//} PACK;
//
//struct fb_ar_data
//{
//	uchar4 ar_magic;		/* 0x200  */
//	uchar ver_major;		/* 0x204  */
//	uchar ver_minor;		/* 0x205  */
//	uchar2 list_used;		/* 0x206  */
//	uchar2 list_size;		/* 0x208  */
//	uchar2 pri_size;		/* 0x20a  */
//	uchar4 ext_size;		/* 0x20c  */
//} PACK;
//FAT16 BPB定义
//struct fat_bs16
//{
//	uchar jb[3];		/* Jump boot  */
//	char on[8];		/* Oem name  */
//	uchar2 bps;		/* Bytes per sector  */
//	uchar spc;		/* Sectors per cluster  */
//	uchar2 nrs;		/* Number of reserved sector  */
//	uchar nf;		/* Number of FATs  */
//	uchar2 nrd;		/* Number of root directory entries  */
//	uchar2 ts16;		/* 16-bit total sector number  */
//	uchar md;		/* Media  */
//	uchar2 fz16;		/* 16-Bit FAT size  */
//	uchar2 spt;		/* Sectors per track  */
//	uchar2 nh;		/* Number of heads  */
//	uchar4 nhs;		/* Number of hidden sectors  */
//	uchar4 ts32;		/* 32-Bit total sectors  */
//	uchar dn;		/* Drive number  */
//	uchar r1;		/* Reserved field 1  */
//	uchar ebs;		/* Extended boot sigature (0x29)  */
//	uchar4 vn;		/* Volume serial number  */
//	char vl[11];		/* Volume label  */
//	char fs[8];		/* File system  */
//	char bc[448];		/* Boot code  */
//	uchar2 bss;		/* Boot sector sigature (0xAA55)  */
//} PACK;
//FAT32 BPB块
//struct fat_bs32
//{
//	uchar jb[3];		/* Jump boot  */
//	char on[8];		/* Oem name  */
//	uchar2 bps;		/* Bytes per sector */
//	uchar spc;		/* Sectors per cluster  */
//	uchar2 nrs;		/* Number of reserved sector  */
//	uchar nf;		/* Number of FATs  */
//	uchar2 nrd;		/* Number of root directory entries  */
//	uchar2 ts16;		/* 16-bit total sector number  */
//	uchar md;		/* Media  */
//	uchar2 fz16;		/* 16-Bit FAT size  */
//	uchar2 spt;		/* Sectors per track  */
//	uchar2 nh;		/* Number of heads  */
//	uchar4 nhs;		/* Number of hidden sectors  */
//	uchar4 ts32;		/* 32-Bit total sectors  */
//	uchar4 fz32;		/* 32-Bit FAT size  */
//	uchar2 ef;		/* Extended flags  */
//	uchar2 fsv;		/* File system version  */
//	uchar4 rc;		/* Root cluster  */
//	uchar2 fsi;		/* Sector number of FSINFO structure (1)  */
//	uchar2 bbs;		/* Backup boot sector (6)  */
//	uchar r1[12];		/* Reserved field 1  */
//	uchar dn;		/* Drive number  */
//	uchar r2;		/* Reserved field 2  */
//	uchar ebs;		/* Extended boot sigature (0x29)  */
//	uchar4 vn;		/* Volume serial number  */
//	char vl[11];		/* Volume label  */
//	char fs[8];		/* File system  */
//	uchar bc[420];	/* Boot code  */
//	uchar2 bss;		/* Boot sector sigature (0xAA55)  */
//} PACK;
//
//struct fbm_file
//{
//	uchar size;
//	uchar flag;
//	uchar4 data_start;
//	uchar4 data_size;
//	time_t data_time;
//	char name[0];
//} PACK;
//
//struct fbm_text
//{
//	uchar size;
//	uchar type;
//	char title[0];
//} PACK;

//struct fbm_menu
//{
//	uchar size;
//	uchar type;
//	uchar2 key;
//	uchar sys_type;
//	char name[0];
//} PACK;
//
//struct fbm_timeout
//{
//	uchar size;
//	uchar type;
//	uchar timeout;
//} PACK;
/* 下面两个结构的用途未知 */
//struct fbm_timeout
//{
//	uchar size;
//	uchar type;
//	uchar timeout;
//} PACK;

//struct fb_ar_data
//{
//	uchar4 ar_magic;		/* 0x200  */
//	uchar ver_major;		/* 0x204  */
//	uchar ver_minor;		/* 0x205  */
//	uchar2 list_used;		/* 0x206  */
//	uchar2 list_size;		/* 0x208  */
//	uchar2 pri_size;		/* 0x20a  */
//	uchar4 ext_size;		/* 0x20c  */
//} PACK;
//





#define FB_MAGIC		"FBBF"
#define FB_MAGIC_LONG		0x46424246
#define FB_MAGIC_WORD		(FB_MAGIC_LONG & 0xffff)


#define FB_AR_MAGIC		"FBAR"
#define FB_AR_MAGIC_LONG	0x52414246
#define FB_AR_MAGIC_WORD	(FB_AR_MAGIC_LONG & 0xffff)
#define FB_AR_MAX_SIZE		0x7fffffff

#define FB_MENU_FILE		"fb.cfg"

#define FBM_TYPE_MENU		1
#define FBM_TYPE_TEXT		2
#define FBM_TYPE_TIMEOUT	3
#define FBM_TYPE_DEFAULT	4
#define FBM_TYPE_COLOR		5

#define FBS_TYPE_MENU		1
#define FBS_TYPE_BULDR		2
#define FBS_TYPE_SYSLINUX	3
#define FBS_TYPE_LINUX		4
#define FBS_TYPE_MSDOS		5
#define FBS_TYPE_FREEDOS	6
#define FBS_TYPE_CHAIN		7
#define FBS_TYPE_GRLDR		8

#define FBF_FLAG_EXTENDED	1
#define FBF_FLAG_SYSLINUX	2

#define OFS_max_sec		0x1ad
#define OFS_lba			0x1ae
#define OFS_bootdrv		0x1af
#define OFS_spt			0x1b0
#define OFS_heads		0x1b1
#define OFS_boot_base		0x1b2
#define OFS_fb_magic		0x1b4
#define OFS_mbr_table		0x1b8

#define OFS_boot_size		0x200
#define OFS_flags		0x202
#define OFS_ver_major		0x204
#define OFS_ver_minor		0x205
#define OFS_list_used		0x206
#define OFS_list_size		0x208
#define OFS_pri_size		0x20a
#define OFS_ext_size		0x20c


#define COLOR_NORMAL		7



#define IOCTL_GET_FBINST_DISKS CTL_CODE(FILE_DEVICE_DISK,0x1,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_FREE_FBINST_DISKS CTL_CODE(FILE_DEVICE_DISK,0x2,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_JUGDE_FBINST_DISK CTL_CODE(FILE_DEVICE_DISK,0x3,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_ADD_NEW_DISK CTL_CODE(FILE_DEVICE_DISK,0x4,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_DELETE_DISK CTL_CODE(FILE_DEVICE_DISK,0x5,METHOD_BUFFERED,FILE_ANY_ACCESS)

//做成数组使用



#define NO_FREE
NTSTATUS FbinstRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FbinstWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
BOOLEAN FbinstFastIoRead(struct _FILE_OBJECT *FileObject,PLARGE_INTEGER FileOffset,ULONG Length,BOOLEAN Wait,ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus,struct _DEVICE_OBJECT *DeviceObject);
BOOLEAN FbinstFastIoWrite(struct _FILE_OBJECT *FileObject,PLARGE_INTEGER FileOffset,ULONG Length,BOOLEAN Wait,ULONG LockKey,PVOID Buffer, PIO_STATUS_BLOCK IoStatus,struct _DEVICE_OBJECT *DeviceObject);
BOOLEAN FBFSFastQueryBasicInfo(struct _FILE_OBJECT *FileObject,BOOLEAN Wait, PFILE_BASIC_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus,struct _DEVICE_OBJECT *DeviceObject);
NTSTATUS FBFSDirectoryControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FBFSQueryFileInfo(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FBFSSetFileInfo(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
BOOLEAN FBFSFastQueryStandardInfo(struct _FILE_OBJECT *FileObject,BOOLEAN Wait, PFILE_STANDARD_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus,struct _DEVICE_OBJECT *DeviceObject);
//BOOLEAN FBFSFastLock(
//struct _FILE_OBJECT *FileObject,
//	PLARGE_INTEGER FileOffset,
//	PLARGE_INTEGER Length,
//	PEPROCESS ProcessId,
//	ULONG Key,
//	BOOLEAN FailImmediately,
//	BOOLEAN ExclusiveLock,
//	PIO_STATUS_BLOCK IoStatus,
//struct _DEVICE_OBJECT *DeviceObject
//	);
NTSTATUS FBFSCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FBFSClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FBFSCleanUp(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FBFSSystemControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FBFSFileSysControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
NTSTATUS FBFSLock(IN PDEVICE_OBJECT DeviceObject,IN PIRP IRPMess);
BOOLEAN FBFSCheckFastIo(IN struct _FILE_OBJECT *FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN BOOLEAN Wait,IN ULONG LockKey,IN BOOLEAN CheckForReadOperation,OUT PIO_STATUS_BLOCK IoStatus,IN struct _DEVICE_OBJECT *DeviceObject);

int EnmuDisk(OUT LIST_ENTRY* pDiskListHead);
int EnmuUD(IN LIST_ENTRY *pDiskListHead,OUT LIST_ENTRY *pUDListHead,IN PDRIVER_OBJECT DriverObject);
void GetUDFileLists(INOUT PLIST_ENTRY udDeviceList);
bool IfIsUD(wchar_t *DiskIDName);
void *memcat(void* Dst,const void* src,unsigned int offest,size_t srcLength);
FileRecord * GetARecord(IN char *Original,OUT FileRecord *Record);
void GetUDFileLists(INOUT PLIST_ENTRY udDeviceList);
void EnmuFileList(INOUT DiskListEntry *Disk);
NTSTATUS FBFSPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP IRPMess);
VOID KeSleep(LONG msec);

void EasyCompleteIRP(PIRP IRPMess,NTSTATUS status,ULONG_PTR Info);
NTSTATUS FBFSReadFile(FileRecord &FileHandle,void *buffer,size_t bufsize,size_t readsize,LARGE_INTEGER offest,IO_STATUS_BLOCK &IoStatus);
NTSTATUS Completion(PDEVICE_OBJECT DeviceObject,PIRP IRPMess,PVOID context);

PLIST_ENTRY SearchVolume(FBFSVolume *VolumeInfo);
unsigned int NumChar(wchar_t *str,wchar_t *substr);

NTSTATUS MakeTree(FBFSVolume &Volume,FileRecord* Start=NULL,FileRecord* Root=NULL);
NTSTATUS SearchFileTree(UNICODE_STRING &FileName,FileRecord * Results[],int resultnum,FBFSVolume &Volume,FileRecord *Start=NULL);
#endif